package net.entelijan.cobean.data.literature;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

import java.util.List;

import net.entelijan.cobean.data.common.Country;
import net.entelijan.cobean.data.common.Language;
import net.entelijan.testutil.CobeanTestUtil;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ServiceTestCase {

	@Test
	public void testLoadAllBooks() {
		ILitService s = createService();
		List<LitBook> books = s.loadAllBooks();
		assertEquals(30, books.size());
		{
			LitBook b = books.get(0);
			assertEquals(62, b.getId());
			assertEquals("Ad ora incerta", b.getTitle());
			assertEquals(null, b.getSubtitle());
			assertEquals(false, b.getTranslation());
			assertEquals(Integer.valueOf(1984), b.getYear());
		}
		{
			LitBook b = books.get(5);
			assertEquals(52, b.getId());
			assertEquals("Miguel Street", b.getTitle());
			assertEquals(null, b.getSubtitle());
			assertEquals(false, b.getTranslation());
			assertEquals(Integer.valueOf(1959), b.getYear());
		}
		{
			LitBook b = books.get(11);
			assertEquals(40, b.getId());
			assertEquals("A Fine Balance", b.getTitle());
			assertEquals(null, b.getSubtitle());
			assertEquals(false, b.getTranslation());
			assertEquals(Integer.valueOf(1996), b.getYear());
		}
		{
			LitBook b = books.get(20);
			assertEquals(20, b.getId());
			assertEquals("The Golden Gate", b.getTitle());
			assertEquals(null, b.getSubtitle());
			assertEquals(false, b.getTranslation());
			assertEquals(Integer.valueOf(1986), b.getYear());
		}
	}

	@Test
	public void testLoadAllAuthors() {
		ILitService s = createService();
		List<LitAuthor> authors = s.loadAllAuthors();
		assertEquals(12, authors.size());
		{
			LitAuthor a = authors.get(0);
			assertEquals(11, a.getId());
			assertEquals("Upamanyu Chatterjee", a.getName());
			assertEquals(null, a.getBirthday());
			assertEquals(Country.INDIA, a.getCountry());
			assertEquals(Language.ENGLISH, a.getLanguage());
		}
		{
			LitAuthor a = authors.get(6);
			assertEquals(5, a.getId());
			assertEquals("Primo Levi", a.getName());
			assertEquals(CobeanTestUtil.createDate("yyyyMMdd", "19190731"), a
					.getBirthday());
			assertEquals(Country.ISRAEL, a.getCountry());
			assertEquals(Language.ITALIAN, a.getLanguage());
		}
	}

	@Test
	public void testLoadAuthor() {
		ILitService s = createService();
		{
			LitAuthor a = s.loadAuthor(11);
			assertEquals(11, a.getId());
			assertEquals("Upamanyu Chatterjee", a.getName());
			assertEquals(null, a.getBirthday());
			assertEquals(Country.INDIA, a.getCountry());
			assertEquals(Language.ENGLISH, a.getLanguage());
			assertNull(a.getBooks());
		}
		{
			LitAuthor a = s.loadAuthor(5);
			assertEquals(5, a.getId());
			assertEquals("Primo Levi", a.getName());
			assertEquals(CobeanTestUtil.createDate("yyyyMMdd", "19190731"), a
					.getBirthday());
			assertEquals(Country.ISRAEL, a.getCountry());
			assertEquals(Language.ITALIAN, a.getLanguage());
			List<LitBook> books = a.getBooks();
			assertNotNull(books);
			assertEquals(3, books.size());
			{
				LitBook b = books.get(2);
				assertEquals(62, b.getId());
				assertEquals("Ad ora incerta", b.getTitle());
				assertEquals(null, b.getSubtitle());
				assertEquals(false, b.getTranslation());
				assertEquals(Integer.valueOf(1984), b.getYear());
			}
		}
	}

	@Test
	public void testLoadBook() {
		ILitService s = createService();
		{
			LitBook b = s.loadBook(3);
			assertEquals(3, b.getId());
			assertEquals("The Jaguar Smile", b.getTitle());
			assertEquals("A Nicaraguan Journey", b.getSubtitle());
			assertEquals(false, b.getTranslation());
			assertEquals(Integer.valueOf(1987), b.getYear());
		}

	}

	@Test
	public void testSaveBookChangeTitle() {
		ILitService s = createService();
		{
			LitBook b = s.loadBook(3);
			assertEquals(3, b.getId());
			assertEquals("The Jaguar Smile", b.getTitle());
			assertEquals("A Nicaraguan Journey", b.getSubtitle());
			assertEquals(false, b.getTranslation());
			assertEquals(Integer.valueOf(1987), b.getYear());

			b.setTitle("The Lion Smile");
			s.saveBook(b);

			b = s.loadBook(3);
			assertEquals(3, b.getId());
			assertEquals("The Lion Smile", b.getTitle());
			assertEquals("A Nicaraguan Journey", b.getSubtitle());
			assertEquals(false, b.getTranslation());
			assertEquals(Integer.valueOf(1987), b.getYear());
		}

	}

	@Test
	public void testSaveAuthor() {
		ILitService s = createService();
		LitAuthor a = s.loadAuthor(11);
		assertEquals("Upamanyu Chatterjee", a.getName());
		a.setName("The new name");

		s.saveAuthor(a);

		a = s.loadAuthor(11);
		assertEquals("The new name", a.getName());

	}

	@Test
	public void testAddBookToAuthor() {
		ILitService s = createService();
		LitAuthor a = s.loadAuthor(5);
		assertEquals("Primo Levi", a.getName());
		assertEquals(3, a.getBooks().size());

		LitBook b = new LitBook();
		b.setTitle("The Book");

		s.saveBook(b);
		s.addBookToAuthor(a, b);

		a = s.loadAuthor(5);
		assertEquals("Primo Levi", a.getName());
		assertEquals(4, a.getBooks().size());

		LitBook b1 = findBookWithTitle(a.getBooks(), "The Book");
		LitAuthor a1 = b1.getAuthor();
		assertEquals("Primo Levi", a1.getName());
	}

	@Test
	public void testRemoveBookFromAuthor() {
		ILitService s = createService();
		LitAuthor a = s.loadAuthor(5);
		assertEquals("Primo Levi", a.getName());
		assertEquals(3, a.getBooks().size());

		a.getBooks().remove(0);

		s.removeBookFromAuthor(a, a.getBooks().get(0));

		a = s.loadAuthor(5);
		assertEquals("Primo Levi", a.getName());
		assertEquals(2, a.getBooks().size());

	}

	@Test
	public void testReloadAuthor() {
		ILitService s = createService();
		LitAuthor a = s.loadAuthor(11);
		assertEquals("Upamanyu Chatterjee", a.getName());
		a.setName("The new name");

		a = s.loadAuthor(11);
		assertEquals("Upamanyu Chatterjee", a.getName());

	}

	@Test
	public void testChangeTitleAndReload() {
		ILitService s = createService();
		{
			LitBook b = s.loadBook(3);
			assertEquals(3, b.getId());
			assertEquals("The Jaguar Smile", b.getTitle());
			assertEquals("A Nicaraguan Journey", b.getSubtitle());
			assertEquals(false, b.getTranslation());
			assertEquals(Integer.valueOf(1987), b.getYear());

			b.setTitle("The Lion Smile");

			b = s.loadBook(3);
			assertEquals(3, b.getId());
			assertEquals("The Jaguar Smile", b.getTitle());
			assertEquals("A Nicaraguan Journey", b.getSubtitle());
			assertEquals(false, b.getTranslation());
			assertEquals(Integer.valueOf(1987), b.getYear());
		}

	}

	@Test
	public void testSaveBookChangeTranslation() {
		ILitService s = createService();
		{
			LitBook b = s.loadBook(3);
			assertEquals(3, b.getId());
			assertEquals("The Jaguar Smile", b.getTitle());
			assertEquals("A Nicaraguan Journey", b.getSubtitle());
			assertEquals(false, b.getTranslation());
			assertEquals(Integer.valueOf(1987), b.getYear());

			b.setTranslation(true);
			s.saveBook(b);

			b = s.loadBook(3);
			assertEquals(3, b.getId());
			assertEquals("The Jaguar Smile", b.getTitle());
			assertEquals("A Nicaraguan Journey", b.getSubtitle());
			assertEquals(true, b.getTranslation());
			assertEquals(Integer.valueOf(1987), b.getYear());
		}

	}

	@Test
	public void testReloadBookAfterChange() {
		ILitService s = createService();
		{
			LitBook b = s.loadBook(3);
			assertEquals(3, b.getId());
			assertEquals("The Jaguar Smile", b.getTitle());
			assertEquals("A Nicaraguan Journey", b.getSubtitle());
			assertEquals(false, b.getTranslation());
			assertEquals(Integer.valueOf(1987), b.getYear());

			b.setTranslation(true);

			b = s.loadBook(3);
			assertEquals(3, b.getId());
			assertEquals("The Jaguar Smile", b.getTitle());
			assertEquals("A Nicaraguan Journey", b.getSubtitle());
			assertEquals(false, b.getTranslation());
			assertEquals(Integer.valueOf(1987), b.getYear());
		}

	}

	private LitBook findBookWithTitle(List<LitBook> books, String title) {
		LitBook re = null;
		for (LitBook b : books) {
			if (title.equals(b.getTitle())) {
				re = b;
				break;
			}
		}
		return re;
	}

	private ILitService createService() {
		ApplicationContext ctx = new ClassPathXmlApplicationContext(
				"lit-service-ctx.xml");
		return (ILitService) ctx.getBean("inmem-service");
	}

}
